<!DOCTYPE html><html class=split lang=en-US-x-hixie><script src=../link-fixup.js defer=""></script>
<!-- Mirrored from html.spec.whatwg.org/multipage/timers-and-user-prompts.html by HTTrack Website Copier/3.x [XR&CO'2014], Wed, 10 Sep 2025 08:35:53 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=utf-8" /><!-- /Added by HTTrack -->
<meta charset=utf-8><meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name=viewport><title>HTML Standard</title><meta content=#3c790a name=theme-color><meta content="light dark" name=color-scheme><link rel=stylesheet href=../../resources.whatwg.org/standard-shared-with-dev.css crossorigin=""><link rel=stylesheet href=../../resources.whatwg.org/standard.css crossorigin=""><link rel=stylesheet href=../../resources.whatwg.org/spec.css crossorigin=""><link rel=icon href=https://resources.whatwg.org/logo.svg crossorigin=""><link rel=stylesheet href=../styles.css crossorigin=""><script>
   function toggleStatus(div) {
     div.parentNode.classList.toggle('wrapped');
   }
   function setLinkFragment(link) {
     link.hash = location.hash;
   }
  </script><body>
  
  <script defer="" crossorigin="" src=../html-dfn.js></script>
  
  <header id=head class="head with-buttons">
   <a href=https://whatwg.org/ class=logo><img width=100 alt=WHATWG crossorigin="" class=darkmode-aware src=https://resources.whatwg.org/logo.svg height=100></a>
   <hgroup><h1 class=allcaps>HTML</h1><p id=living-standard>Living Standard — Last Updated <span class=pubdate>10 September 2025</span></hgroup>
   
   

   
  </header>

  

  

  

  
  

  
  

  

  <nav><a href=dynamic-markup-insertion.html>← 8.4 Dynamic markup insertion</a> — <a href=index.html>Table of Contents</a> — <a href=system-state.html>8.9 System state and capabilities →</a></nav><ol class=toc><li id=toc-webappapis><ol><li><a href=timers-and-user-prompts.html#timers><span class=secno>8.6</span> Timers</a><li><a href=timers-and-user-prompts.html#microtask-queuing><span class=secno>8.7</span> Microtask queuing</a><li><a href=timers-and-user-prompts.html#user-prompts><span class=secno>8.8</span> User prompts</a><ol><li><a href=timers-and-user-prompts.html#simple-dialogs><span class=secno>8.8.1</span> Simple dialogs</a><li><a href=timers-and-user-prompts.html#printing><span class=secno>8.8.2</span> Printing</a></ol></ol></ol><h3 id=timers><span class=secno>8.6</span> Timers<a href=#timers class=self-link></a></h3>

  <p>The <code id=timers:dom-settimeout><a href=#dom-settimeout>setTimeout()</a></code> and <code id=timers:dom-setinterval><a href=#dom-setinterval>setInterval()</a></code> methods allow authors to schedule timer-based
  callbacks.</p>

  <dl class=domintro><dt><code><var>id</var> = self.<a href=#dom-settimeout id=dom-settimeout-dev>setTimeout</a>(<var>handler</var> [, <var>timeout</var> [, ...<var>arguments</var> ] ])</code><div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/setTimeout title="The global setTimeout() method sets a timer which executes a function or specified piece of code once the timer expires.">setTimeout</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>1+</span></span><span class="safari yes"><span>Safari</span><span>1+</span></span><span class="chrome yes"><span>Chrome</span><span>1+</span></span><hr><span class="opera yes"><span>Opera</span><span>4+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>4+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>10.1+</span></span></div></div></div><dd>
    <p>Schedules a timeout to run <var>handler</var> after <var>timeout</var> milliseconds. Any
    <var>arguments</var> are passed straight through to the <var>handler</var>.</p>
   <dt><code><var>id</var> = self.<a href=#dom-settimeout id=timers:dom-settimeout-2>setTimeout</a>(<var>code</var> [, <var>timeout</var> ])</code><dd>
    <p>Schedules a timeout to compile and run <var>code</var> after <var>timeout</var>
    milliseconds.</p>
   <dt><code>self.<a href=#dom-cleartimeout id=dom-cleartimeout-dev>clearTimeout</a>(<var>id</var>)</code><div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout title="The global clearTimeout() method cancels a timeout previously established by calling setTimeout().">clearTimeout</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>1+</span></span><span class="safari yes"><span>Safari</span><span>4+</span></span><span class="chrome yes"><span>Chrome</span><span>1+</span></span><hr><span class="opera yes"><span>Opera</span><span>4+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>4+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios yes"><span>Safari iOS</span><span>1+</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android yes"><span>WebView Android</span><span>37+</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>10.1+</span></span></div></div></div><dd><p>Cancels the timeout set with <code id=timers:dom-settimeout-3><a href=#dom-settimeout>setTimeout()</a></code> or <code id=timers:dom-setinterval-2><a href=#dom-setinterval>setInterval()</a></code> identified by <var>id</var>.<dt><code><var>id</var> = self.<a href=#dom-setinterval id=dom-setinterval-dev>setInterval</a>(<var>handler</var> [, <var>timeout</var> [, ...<var>arguments</var> ] ])</code><div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/setInterval title="The setInterval() method, offered on the Window and Worker interfaces, repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.">setInterval</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>1+</span></span><span class="safari yes"><span>Safari</span><span>1+</span></span><span class="chrome yes"><span>Chrome</span><span>1+</span></span><hr><span class="opera yes"><span>Opera</span><span>4+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>4+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>10.1+</span></span></div></div></div><dd>
    <p>Schedules a timeout to run <var>handler</var> every <var>timeout</var> milliseconds. Any
    <var>arguments</var> are passed straight through to the <var>handler</var>.</p>
   <dt><code><var>id</var> = self.<a href=#dom-setinterval id=timers:dom-setinterval-3>setInterval</a>(<var>code</var> [, <var>timeout</var> ])</code><dd>
    <p>Schedules a timeout to compile and run <var>code</var> every <var>timeout</var>
    milliseconds.</p>
   <dt><code>self.<a href=#dom-clearinterval id=dom-clearinterval-dev>clearInterval</a>(<var>id</var>)</code><div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/clearInterval title="The global clearInterval() method cancels a timed, repeating action which was previously established by a call to setInterval(). If the parameter provided does not identify a previously established action, this method does nothing.">clearInterval</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>1+</span></span><span class="safari yes"><span>Safari</span><span>1+</span></span><span class="chrome yes"><span>Chrome</span><span>1+</span></span><hr><span class="opera yes"><span>Opera</span><span>4+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>4+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android yes"><span>WebView Android</span><span>37+</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>10.1+</span></span></div></div></div><dd><p>Cancels the timeout set with <code id=timers:dom-setinterval-4><a href=#dom-setinterval>setInterval()</a></code> or <code id=timers:dom-settimeout-4><a href=#dom-settimeout>setTimeout()</a></code> identified by <var>id</var>.</dl>

  <p class=note>Timers can be nested; after five such nested timers, however, the interval is
  forced to be at least four milliseconds.</p>

  <p class=note>This API does not guarantee that timers will run exactly on schedule. Delays due
  to CPU load, other tasks, etc, are to be expected.</p>

  

  <p>Objects that implement the <code id=timers:windoworworkerglobalscope><a href=webappapis.html#windoworworkerglobalscope>WindowOrWorkerGlobalScope</a></code> mixin have a
  <dfn data-dfn-for=WindowOrWorkerGlobalScope id=map-of-settimeout-and-setinterval-ids data-export="">map of setTimeout and setInterval IDs</dfn>, which is
  an <a id=timers:ordered-map href=https://infra.spec.whatwg.org/#ordered-map data-x-internal=ordered-map>ordered map</a>, initially empty. Each <a href=https://infra.spec.whatwg.org/#map-key id=timers:map-key data-x-internal=map-key>key</a> in this map
  is a positive integer, corresponding to the return value of a <code id=timers:dom-settimeout-5><a href=#dom-settimeout>setTimeout()</a></code> or <code id=timers:dom-setinterval-5><a href=#dom-setinterval>setInterval()</a></code> call.
  Each <a href=https://infra.spec.whatwg.org/#map-value id=timers:map-value data-x-internal=map-value>value</a> is a <a id=timers:unique-internal-value href=common-microsyntaxes.html#unique-internal-value>unique internal value</a>, corresponding
  to a key in the object's <a href=#map-of-active-timers id=timers:map-of-active-timers>map of active timers</a>.</p>

  <hr>

  <p>The <dfn data-dfn-for=WindowOrWorkerGlobalScope id=dom-settimeout data-dfn-type=method><code id=dom-windowtimers-setTimeout>setTimeout(<var>handler</var>, <var>timeout</var>,
  ...<var>arguments</var>)</code></dfn> method steps are to return the result of running the
  <a href=#timer-initialisation-steps id=timers:timer-initialisation-steps>timer initialization steps</a> given <a id=timers:this href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>, <var>handler</var>,
  <var>timeout</var>, <var>arguments</var>, and false.</p>

  <p>The <dfn data-dfn-for=WindowOrWorkerGlobalScope id=dom-setinterval data-dfn-type=method><code id=dom-windowtimers-setInterval>setInterval(<var>handler</var>, <var>timeout</var>,
  ...<var>arguments</var>)</code></dfn> method steps are to return the result of running the
  <a href=#timer-initialisation-steps id=timers:timer-initialisation-steps-2>timer initialization steps</a> given <a id=timers:this-2 href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>, <var>handler</var>,
  <var>timeout</var>, <var>arguments</var>, and true.</p>

  <p>The <dfn data-dfn-for=WindowOrWorkerGlobalScope id=dom-cleartimeout data-dfn-type=method><code id=dom-windowtimers-clearTimeout>clearTimeout(<var>id</var>)</code></dfn> and <dfn data-dfn-for=WindowOrWorkerGlobalScope id=dom-clearinterval data-dfn-type=method><code id=dom-windowtimers-clearInterval>clearInterval(<var>id</var>)</code></dfn> method steps
  are to <a href=https://infra.spec.whatwg.org/#map-remove id=timers:map-remove data-x-internal=map-remove>remove</a> <a id=timers:this-3 href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>'s <a href=#map-of-settimeout-and-setinterval-ids id=timers:map-of-settimeout-and-setinterval-ids>map of setTimeout and
  setInterval IDs</a>[<var>id</var>].</p>

  <p class=note>Because <code id=timers:dom-cleartimeout><a href=#dom-cleartimeout>clearTimeout()</a></code> and <code id=timers:dom-clearinterval><a href=#dom-clearinterval>clearInterval()</a></code> clear entries from the same map, either method
  can be used to clear timers created by <code id=timers:dom-settimeout-6><a href=#dom-settimeout>setTimeout()</a></code> or <code id=timers:dom-setinterval-6><a href=#dom-setinterval>setInterval()</a></code>.</p>

  <hr>

  <p>To perform the <dfn id=timer-initialisation-steps>timer initialization
  steps</dfn>, given a <code id=timers:windoworworkerglobalscope-2><a href=webappapis.html#windoworworkerglobalscope>WindowOrWorkerGlobalScope</a></code> <var>global</var>, a string or <code id=timers:idl-function><a data-x-internal=idl-function href=https://webidl.spec.whatwg.org/#common-Function>Function</a></code> or <code id=timers:tt-trustedscript><a data-x-internal=tt-trustedscript href=https://w3c.github.io/trusted-types/dist/spec/#trusted-script>TrustedScript</a></code>
  <var>handler</var>, a number <var>timeout</var>, a list <var>arguments</var>, a boolean
  <var>repeat</var>, and optionally (and only if <var>repeat</var> is true) a number
  <var>previousId</var>, perform the following steps. They return a number.</p>

  <ol><li><p>Let <var>thisArg</var> be <var>global</var> if that is a <code id=timers:workerglobalscope><a href=workers.html#workerglobalscope>WorkerGlobalScope</a></code>
   object; otherwise let <var>thisArg</var> be the <code id=timers:windowproxy><a href=nav-history-apis.html#windowproxy>WindowProxy</a></code> that corresponds to
   <var>global</var>.<li><p>If <var>previousId</var> was given, let <var>id</var> be <var>previousId</var>;
   otherwise, let <var>id</var> be an <a id=timers:implementation-defined href=https://infra.spec.whatwg.org/#implementation-defined data-x-internal=implementation-defined>implementation-defined</a> integer that is greater
   than zero and does not already <a href=https://infra.spec.whatwg.org/#map-exists id=timers:map-exists data-x-internal=map-exists>exist</a> in <var>global</var>'s
   <a href=#map-of-settimeout-and-setinterval-ids id=timers:map-of-settimeout-and-setinterval-ids-2>map of setTimeout and setInterval IDs</a>.<li>
    <p>If the <a id=timers:surrounding-agent href=https://tc39.es/ecma262/#surrounding-agent data-x-internal=surrounding-agent>surrounding agent</a>'s <a href=webappapis.html#concept-agent-event-loop id=timers:concept-agent-event-loop>event
    loop</a>'s <a id=timers:currently-running-task href=webappapis.html#currently-running-task>currently running task</a> is a task that was created by this algorithm,
    then let <var>nesting level</var> be the <a href=webappapis.html#concept-task id=timers:concept-task>task</a>'s <a href=#timer-nesting-level id=timers:timer-nesting-level>timer
    nesting level</a>. Otherwise, let <var>nesting level</var> be 0.</p>

    <p class=note>The task's <a href=#timer-nesting-level id=timers:timer-nesting-level-2>timer nesting level</a> is used both for nested calls to
    <code id=timers:dom-settimeout-7><a href=#dom-settimeout>setTimeout()</a></code>, and for the repeating timers created by
    <code id=timers:dom-setinterval-7><a href=#dom-setinterval>setInterval()</a></code>. (Or, indeed, for any combination of the
    two.) In other words, it represents nested invocations of this algorithm, not of a particular
    method.</p>
   <li><p>If <var>timeout</var> is less than 0, then set <var>timeout</var> to 0.<li><p>If <var>nesting level</var> is greater than 5, and <var>timeout</var> is less than 4,
   then set <var>timeout</var> to 4.<li><p>Let <var>realm</var> be <var>global</var>'s <a href=webappapis.html#concept-relevant-realm id=timers:concept-relevant-realm>relevant
   realm</a>.<li><p>Let <var>initiating script</var> be the <a id=timers:active-script href=webappapis.html#active-script>active script</a>.<li><p>Let <var>uniqueHandle</var> be null.<li>
    <p>Let <var>task</var> be a <a href=webappapis.html#concept-task id=timers:concept-task-2>task</a> that runs the following
    substeps:</p>

    <ol><li><p><a id=timers:assert href=https://infra.spec.whatwg.org/#assert data-x-internal=assert>Assert</a>: <var>uniqueHandle</var> is a <a id=timers:unique-internal-value-2 href=common-microsyntaxes.html#unique-internal-value>unique internal value</a>,
     not null.<li><p>If <var>id</var> does not <a href=https://infra.spec.whatwg.org/#map-exists id=timers:map-exists-2 data-x-internal=map-exists>exist</a> in <var>global</var>'s
     <a href=#map-of-settimeout-and-setinterval-ids id=timers:map-of-settimeout-and-setinterval-ids-3>map of setTimeout and setInterval IDs</a>, then abort these steps.<li>
      <p>If <var>global</var>'s <a href=#map-of-settimeout-and-setinterval-ids id=timers:map-of-settimeout-and-setinterval-ids-4>map of setTimeout and setInterval IDs</a>[<var>id</var>]
      does not equal <var>uniqueHandle</var>, then abort these steps.</p>

      <p class=note>This accommodates for the ID having been cleared by a <code id=timers:dom-cleartimeout-2><a href=#dom-cleartimeout>clearTimeout()</a></code> or <code id=timers:dom-clearinterval-2><a href=#dom-clearinterval>clearInterval()</a></code> call, and being reused by a subsequent
      <code id=timers:dom-settimeout-8><a href=#dom-settimeout>setTimeout()</a></code> or <code id=timers:dom-setinterval-8><a href=#dom-setinterval>setInterval()</a></code> call.</p>
     <li><p><a id=timers:record-timing-info-for-timer-handler href=https://w3c.github.io/long-animation-frames/#record-timing-info-for-timer-handler data-x-internal=record-timing-info-for-timer-handler>Record timing info for timer handler</a> given <var>handler</var>,
     <var>global</var>'s <a id=timers:relevant-settings-object href=webappapis.html#relevant-settings-object>relevant settings object</a>, and <var>repeat</var>.<li><p>If <var>handler</var> is a <code id=timers:idl-function-2><a data-x-internal=idl-function href=https://webidl.spec.whatwg.org/#common-Function>Function</a></code>, then <a href=https://webidl.spec.whatwg.org/#invoke-a-callback-function id=timers:es-invoking-callback-functions data-x-internal=es-invoking-callback-functions>invoke</a> <var>handler</var> given
     <var>arguments</var> and "<code>report</code>", and with <i id=timers:dfn-callback-this-value><a data-x-internal=dfn-callback-this-value href=https://webidl.spec.whatwg.org/#dfn-callback-this-value>callback this value</a></i> set to <var>thisArg</var>.</p>
     <li>
      <p>Otherwise:</p>

      <ol><li>
        <p>If <var>previousId</var> was not given:</p>

        <ol><li><p>Let <var>globalName</var> be "<code>Window</code>" if <var>global</var> is
         a <code id=timers:window><a href=nav-history-apis.html#window>Window</a></code> object; "<code>WorkerGlobalScope</code>"
         otherwise.<li><p>Let <var>methodName</var> be "<code>setInterval</code>" if
         <var>repeat</var> is true; "<code>setTimeout</code>" otherwise.<li><p>Let <var>sink</var> be a concatenation of <var>globalName</var>, U+0020 SPACE, and
         <var>methodName</var>.<li><p>Set <var>handler</var> to the result of invoking the <a href=https://w3c.github.io/trusted-types/dist/spec/#get-trusted-type-compliant-string-algorithm id=timers:tt-getcompliantstring data-x-internal=tt-getcompliantstring>Get Trusted Type compliant string</a> algorithm with
         <code id=timers:tt-trustedscript-2><a data-x-internal=tt-trustedscript href=https://w3c.github.io/trusted-types/dist/spec/#trusted-script>TrustedScript</a></code>, <var>global</var>,
         <var>handler</var>, <var>sink</var>, and "<code>script</code>".</ol>
       <li><p><a id=timers:assert-2 href=https://infra.spec.whatwg.org/#assert data-x-internal=assert>Assert</a>: <var>handler</var> is a string.<li><p>Perform <a href=https://w3c.github.io/webappsec-csp/#can-compile-strings id=timers:csp-ensurecspdoesnotblockstringcompilation data-x-internal=csp-ensurecspdoesnotblockstringcompilation>EnsureCSPDoesNotBlockStringCompilation</a>(<var>realm</var>,
       « », <var>handler</var>, <var>handler</var>, timer, « », <var>handler</var>). If this throws
       an exception, catch it, <a href=webappapis.html#report-an-exception id=timers:report-an-exception>report</a> it for
       <var>global</var>, and abort these steps.<li><p>Let <var>settings object</var> be <var>global</var>'s <a id=timers:relevant-settings-object-2 href=webappapis.html#relevant-settings-object>relevant settings
       object</a>.<li><p>Let <var>fetch options</var> be the <a id=timers:default-script-fetch-options href=webappapis.html#default-script-fetch-options>default script fetch
       options</a>.<li><p>Let <var>base URL</var> be <var>settings object</var>'s <a id=timers:api-base-url href=webappapis.html#api-base-url>API base
       URL</a>.<li>
        <p>If <var>initiating script</var> is not null, then:</p>

        <ol><li><p>Set <var>fetch options</var> to a <a id=timers:script-fetch-options href=webappapis.html#script-fetch-options>script fetch options</a> whose <a href=webappapis.html#concept-script-fetch-options-nonce id=timers:concept-script-fetch-options-nonce>cryptographic nonce</a> is <var>initiating
         script</var>'s <a href=webappapis.html#concept-script-script-fetch-options id=timers:concept-script-script-fetch-options>fetch options</a>'s
         <a href=webappapis.html#concept-script-fetch-options-nonce id=timers:concept-script-fetch-options-nonce-2>cryptographic nonce</a>, <a href=webappapis.html#concept-script-fetch-options-integrity id=timers:concept-script-fetch-options-integrity>integrity metadata</a> is the empty
         string, <a href=webappapis.html#concept-script-fetch-options-parser id=timers:concept-script-fetch-options-parser>parser metadata</a> is
         "<code>not-parser-inserted</code>", <a href=webappapis.html#concept-script-fetch-options-credentials id=timers:concept-script-fetch-options-credentials>credentials mode</a> is
         <var>initiating script</var>'s <a href=webappapis.html#concept-script-script-fetch-options id=timers:concept-script-script-fetch-options-2>fetch
         options</a>'s <a href=webappapis.html#concept-script-fetch-options-credentials id=timers:concept-script-fetch-options-credentials-2>credentials
         mode</a>, <a href=webappapis.html#concept-script-fetch-options-referrer-policy id=timers:concept-script-fetch-options-referrer-policy>referrer
         policy</a> is <var>initiating script</var>'s <a href=webappapis.html#concept-script-script-fetch-options id=timers:concept-script-script-fetch-options-3>fetch options</a>'s <a href=webappapis.html#concept-script-fetch-options-referrer-policy id=timers:concept-script-fetch-options-referrer-policy-2>referrer policy</a>, and <a href=webappapis.html#concept-script-fetch-options-fetch-priority id=timers:concept-script-fetch-options-fetch-priority>fetch priority</a> is "<code>auto</code>".<li><p>Set <var>base URL</var> to <var>initiating script</var>'s <a href=webappapis.html#concept-script-base-url id=timers:concept-script-base-url>base URL</a>.</ol>

        <p class=note>The effect of these steps ensures that the string compilation done by <code id=timers:dom-settimeout-9><a href=#dom-settimeout>setTimeout()</a></code> and <code id=timers:dom-setinterval-9><a href=#dom-setinterval>setInterval()</a></code> behaves equivalently to that done by
        <code id=timers:eval()><a data-x-internal=eval() href=https://tc39.es/ecma262/#sec-eval-x>eval()</a></code>. That is, <a id=timers:module-script href=webappapis.html#module-script>module script</a> fetches via <code id=timers:import()><a data-x-internal=import() href=https://tc39.es/ecma262/#sec-import-calls>import()</a></code>
        will behave the same in both contexts.</p>
       <li><p>Let <var>script</var> be the result of <a id=timers:creating-a-classic-script href=webappapis.html#creating-a-classic-script>creating a classic script</a> given
       <var>handler</var>, <var>settings object</var>, <var>base URL</var>, and <var>fetch
       options</var>.<li><p><a href=webappapis.html#run-a-classic-script id=timers:run-a-classic-script>Run the classic script</a>
       <var>script</var>.</ol>
     <li><p>If <var>id</var> does not <a href=https://infra.spec.whatwg.org/#map-exists id=timers:map-exists-3 data-x-internal=map-exists>exist</a> in <var>global</var>'s
     <a href=#map-of-settimeout-and-setinterval-ids id=timers:map-of-settimeout-and-setinterval-ids-5>map of setTimeout and setInterval IDs</a>, then abort these steps.<li>
      <p>If <var>global</var>'s <a href=#map-of-settimeout-and-setinterval-ids id=timers:map-of-settimeout-and-setinterval-ids-6>map of setTimeout and setInterval IDs</a>[<var>id</var>]
      does not equal <var>uniqueHandle</var>, then abort these steps.</p>

      <p class=note>The ID might have been removed via the author code in <var>handler</var>
      calling <code id=timers:dom-cleartimeout-3><a href=#dom-cleartimeout>clearTimeout()</a></code> or <code id=timers:dom-clearinterval-3><a href=#dom-clearinterval>clearInterval()</a></code>. Checking that uniqueHandle isn't different
      accounts for the possibility of the ID, after having been cleared, being reused by a
      subsequent <code id=timers:dom-settimeout-10><a href=#dom-settimeout>setTimeout()</a></code> or <code id=timers:dom-setinterval-10><a href=#dom-setinterval>setInterval()</a></code> call.</p>
     <li><p>If <var>repeat</var> is true, then perform the <a href=#timer-initialisation-steps id=timers:timer-initialisation-steps-3>timer initialization
     steps</a> again, given <var>global</var>, <var>handler</var>, <var>timeout</var>,
     <var>arguments</var>, true, and <var>id</var>.<li><p>Otherwise, <a href=https://infra.spec.whatwg.org/#map-remove id=timers:map-remove-2 data-x-internal=map-remove>remove</a> <var>global</var>'s <a href=#map-of-settimeout-and-setinterval-ids id=timers:map-of-settimeout-and-setinterval-ids-7>map of
     setTimeout and setInterval IDs</a>[<var>id</var>].</ol>
   <li><p>Increment <var>nesting level</var> by one.<li><p>Set <var>task</var>'s <dfn id=timer-nesting-level>timer nesting level</dfn> to <var>nesting level</var>.<li><p>Let <var>completionStep</var> be an algorithm step which <a href=webappapis.html#queue-a-global-task id=timers:queue-a-global-task>queues a global task</a> on the <dfn id=timer-task-source data-export="">timer task source</dfn> given
   <var>global</var> to run <var>task</var>.<li><p>Set <var>uniqueHandle</var> to the result of <a href=#run-steps-after-a-timeout id=timers:run-steps-after-a-timeout>running steps after a timeout</a> given <var>global</var>, "<code>setTimeout/setInterval</code>", <var>timeout</var>, and
   <var>completionStep</var>.<li><p><a href=https://infra.spec.whatwg.org/#map-set id=timers:map-set data-x-internal=map-set>Set</a> <var>global</var>'s <a href=#map-of-settimeout-and-setinterval-ids id=timers:map-of-settimeout-and-setinterval-ids-8>map of setTimeout and
   setInterval IDs</a>[<var>id</var>] to <var>uniqueHandle</var>.<li><p>Return <var>id</var>.</ol>

  <p class=note>Argument conversion as defined by Web IDL (for example, invoking <code>toString()</code> methods on objects passed as the first argument) happens in the
  algorithms defined in Web IDL, before this algorithm is invoked.</p>

  <div class=example>
   <p>So for example, the following rather silly code will result in the log containing "<code>ONE TWO </code>":</p>

   <pre><code class='js'><c- a>var</c-> log <c- o>=</c-> <c- t>&apos;&apos;</c-><c- p>;</c->
<c- a>function</c-> logger<c- p>(</c->s<c- p>)</c-> <c- p>{</c-> log <c- o>+=</c-> s <c- o>+</c-> <c- t>&apos; &apos;</c-><c- p>;</c-> <c- p>}</c->

setTimeout<c- p>({</c-> toString<c- o>:</c-> <c- a>function</c-> <c- p>()</c-> <c- p>{</c->
  setTimeout<c- p>(</c-><c- u>&quot;logger(&apos;ONE&apos;)&quot;</c-><c- p>,</c-> <c- mf>100</c-><c- p>);</c->
  <c- k>return</c-> <c- u>&quot;logger(&apos;TWO&apos;)&quot;</c-><c- p>;</c->
<c- p>}</c-> <c- p>},</c-> <c- mf>100</c-><c- p>);</c-></code></pre>
  </div>

  

  <div class=example>
   <p>To run tasks of several milliseconds back to back without any delay, while still yielding back
   to the browser to avoid starving the user interface (and to avoid the browser killing the script
   for hogging the CPU), simply queue the next timer before performing work:</p>

   <pre><code class='js'><c- a>function</c-> doExpensiveWork<c- p>()</c-> <c- p>{</c->
  <c- a>var</c-> done <c- o>=</c-> <c- kc>false</c-><c- p>;</c->
  <c- c1>// ...</c->
  <c- c1>// this part of the function takes up to five milliseconds</c->
  <c- c1>// set done to true if we&apos;re done</c->
  <c- c1>// ...</c->
  <c- k>return</c-> done<c- p>;</c->
<c- p>}</c->

<c- a>function</c-> rescheduleWork<c- p>()</c-> <c- p>{</c->
  <c- a>var</c-> id <c- o>=</c-> setTimeout<c- p>(</c->rescheduleWork<c- p>,</c-> <c- mf>0</c-><c- p>);</c-> <c- c1>// preschedule next iteration</c->
  <c- k>if</c-> <c- p>(</c->doExpensiveWork<c- p>())</c->
    clearTimeout<c- p>(</c->id<c- p>);</c-> <c- c1>// clear the timeout if we don&apos;t need it</c->
<c- p>}</c->

<c- a>function</c-> scheduleWork<c- p>()</c-> <c- p>{</c->
  setTimeout<c- p>(</c->rescheduleWork<c- p>,</c-> <c- mf>0</c-><c- p>);</c->
<c- p>}</c->

scheduleWork<c- p>();</c-> <c- c1>// queues a task to do lots of work</c-></code></pre>
  </div>

  

  <p>Objects that implement the <code id=timers:windoworworkerglobalscope-3><a href=webappapis.html#windoworworkerglobalscope>WindowOrWorkerGlobalScope</a></code> mixin have a <dfn data-dfn-for=WindowOrWorkerGlobalScope id=map-of-active-timers data-export="">map of active timers</dfn>, which is an <a id=timers:ordered-map-2 href=https://infra.spec.whatwg.org/#ordered-map data-x-internal=ordered-map>ordered map</a>,
  initially empty. Each <a href=https://infra.spec.whatwg.org/#map-key id=timers:map-key-2 data-x-internal=map-key>key</a> in this map is a <a id=timers:unique-internal-value-3 href=common-microsyntaxes.html#unique-internal-value>unique internal
  value</a> that represents a timer, and each <a href=https://infra.spec.whatwg.org/#map-value id=timers:map-value-2 data-x-internal=map-value>value</a> is a
  <code id=timers:domhighrestimestamp><a data-x-internal=domhighrestimestamp href=https://w3c.github.io/hr-time/#dom-domhighrestimestamp>DOMHighResTimeStamp</a></code>, representing the expiry time for that timer.</p>

  <p>To <dfn id=run-steps-after-a-timeout data-export="">run steps after a timeout</dfn>, given a <code id=timers:windoworworkerglobalscope-4><a href=webappapis.html#windoworworkerglobalscope>WindowOrWorkerGlobalScope</a></code>
  <var>global</var>, a string <var>orderingIdentifier</var>, a number <var>milliseconds</var>, and a
  set of steps <var>completionSteps</var>, perform the following steps. They return a <a id=timers:unique-internal-value-4 href=common-microsyntaxes.html#unique-internal-value>unique
  internal value</a>.</p>

  <ol><li><p>Let <var>timerKey</var> be a new <a id=timers:unique-internal-value-5 href=common-microsyntaxes.html#unique-internal-value>unique internal value</a>.<li><p>Let <var>startTime</var> be the <a id=timers:current-high-resolution-time href=https://w3c.github.io/hr-time/#dfn-current-high-resolution-time data-x-internal=current-high-resolution-time>current high resolution time</a> given
   <var>global</var>.<li><p><a href=https://infra.spec.whatwg.org/#map-set id=timers:map-set-2 data-x-internal=map-set>Set</a> <var>global</var>'s <a href=#map-of-active-timers id=timers:map-of-active-timers-2>map of active
   timers</a>[<var>timerKey</var>] to <var>startTime</var> plus
   <var>milliseconds</var>.<li>
    <p>Run the following steps <a id=timers:in-parallel href=infrastructure.html#in-parallel>in parallel</a>:</p>

    <ol><li>
      <p>If <var>global</var> is a <code id=timers:window-2><a href=nav-history-apis.html#window>Window</a></code> object, wait until <var>global</var>'s <a href=nav-history-apis.html#concept-document-window id=timers:concept-document-window>associated <code>Document</code></a> has been <a id=timers:fully-active href=document-sequences.html#fully-active>fully
      active</a> for a further <var>milliseconds</var> milliseconds (not necessarily
      consecutively).</p>

      <p>Otherwise, <var>global</var> is a <code id=timers:workerglobalscope-2><a href=workers.html#workerglobalscope>WorkerGlobalScope</a></code> object; wait until
      <var>milliseconds</var> milliseconds have passed with the worker not suspended (not
      necessarily consecutively).</p>
     <li><p>Wait until any invocations of this algorithm that had the same <var>global</var> and
     <var>orderingIdentifier</var>, that started before this one, and whose <var>milliseconds</var>
     is less than or equal to this one's, have completed.<li>
      <p>Optionally, wait a further <a id=timers:implementation-defined-2 href=https://infra.spec.whatwg.org/#implementation-defined data-x-internal=implementation-defined>implementation-defined</a> length of time.</p>

      <p class=note>This is intended to allow user agents to pad timeouts as needed to optimize
      the power usage of the device. For example, some processors have a low-power mode where the
      granularity of timers is reduced; on such platforms, user agents can slow timers down to fit
      this schedule instead of requiring the processor to use the more accurate mode with its
      associated higher power usage.</p>
     <li><p>Perform <var>completionSteps</var>.<li><p><a href=https://infra.spec.whatwg.org/#map-remove id=timers:map-remove-3 data-x-internal=map-remove>Remove</a> <var>global</var>'s
     <a href=#map-of-active-timers id=timers:map-of-active-timers-3>map of active timers</a>[<var>timerKey</var>].</ol>
   <li><p>Return <var>timerKey</var>.</ol>

  <p class=note><a href=#run-steps-after-a-timeout id=timers:run-steps-after-a-timeout-2>Run steps after a timeout</a> is meant to be used by other
  specifications that want to execute developer-supplied code after a developer-supplied timeout,
  in a similar manner to <code id=timers:dom-settimeout-11><a href=#dom-settimeout>setTimeout()</a></code>. (Note, however, it does
  not have the nesting and clamping behavior of <code id=timers:dom-settimeout-12><a href=#dom-settimeout>setTimeout()</a></code>.)
  Such specifications can choose an <var>orderingIdentifier</var> to ensure ordering within their
  specification's timeouts, while not constraining ordering with respect to other specification's
  timeouts.</p>

  

  <h3 id=microtask-queuing><span class=secno>8.7</span> Microtask queuing<a href=#microtask-queuing class=self-link></a></h3><div class="mdn-anno wrapped"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask title="The queueMicrotask() method, which is exposed on the Window or Worker interface, queues a microtask to be executed at a safe time prior to control returning to the browser's event loop.">queueMicrotask</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>69+</span></span><span class="safari yes"><span>Safari</span><span>12.1+</span></span><span class="chrome yes"><span>Chrome</span><span>71+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge unknown"><span>Edge (Legacy)</span><span>?</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android unknown"><span>Opera Android</span><span>?</span></span></div></div></div>

  <dl class=domintro><dt><code><var>self</var>.<a href=#dom-queuemicrotask id=dom-queuemicrotask-dev>queueMicrotask</a>(<var>callback</var>)</code><dd><p><a href=webappapis.html#queue-a-microtask id=microtask-queuing:queue-a-microtask>Queues</a> a <a id=microtask-queuing:microtask href=webappapis.html#microtask>microtask</a> to run the given
   <var>callback</var>.</dl>

  <p>The <dfn data-dfn-for=WindowOrWorkerGlobalScope id=dom-queuemicrotask data-dfn-type=method><code>queueMicrotask(<var>callback</var>)</code></dfn> method must
  <a id=microtask-queuing:queue-a-microtask-2 href=webappapis.html#queue-a-microtask>queue a microtask</a> to <a href=https://webidl.spec.whatwg.org/#invoke-a-callback-function id=microtask-queuing:es-invoking-callback-functions data-x-internal=es-invoking-callback-functions>invoke</a>
  <var>callback</var> with « » and "<code>report</code>".</p>

  <p>The <code id=microtask-queuing:dom-queuemicrotask><a href=#dom-queuemicrotask>queueMicrotask()</a></code> method allows authors to schedule
  a callback on the <a id=microtask-queuing:microtask-queue href=webappapis.html#microtask-queue>microtask queue</a>. This allows their code to run once the
  <a id=microtask-queuing:javascript-execution-context-stack href=https://tc39.es/ecma262/#execution-context-stack data-x-internal=javascript-execution-context-stack>JavaScript execution context stack</a> is next empty, which happens once all currently
  executing synchronous JavaScript has run to completion. This doesn't yield control back to the
  <a id=microtask-queuing:event-loop href=webappapis.html#event-loop>event loop</a>, as would be the case when using, for example, <code id=microtask-queuing:dom-settimeout><a href=#dom-settimeout>setTimeout(<var>f</var>, 0)</a></code>.</p>

  <p>Authors ought to be aware that scheduling a lot of microtasks has the same performance
  downsides as running a lot of synchronous code. Both will prevent the browser from doing its own
  work, such as rendering. In many cases, <code id=microtask-queuing:dom-animationframeprovider-requestanimationframe><a href=imagebitmap-and-animations.html#dom-animationframeprovider-requestanimationframe>requestAnimationFrame()</a></code> or
  <code id=microtask-queuing:requestidlecallback()><a data-x-internal=requestidlecallback() href=https://w3c.github.io/requestidlecallback/#the-requestidlecallback-method>requestIdleCallback()</a></code> is a better choice. In particular, if the goal is to run code
  before the next rendering cycle, that is the purpose of <code id=microtask-queuing:dom-animationframeprovider-requestanimationframe-2><a href=imagebitmap-and-animations.html#dom-animationframeprovider-requestanimationframe>requestAnimationFrame()</a></code>.</p>

  <p>As can be seen from the following examples, the best way of thinking about <code id=microtask-queuing:dom-queuemicrotask-2><a href=#dom-queuemicrotask>queueMicrotask()</a></code> is as a mechanism for rearranging synchronous
  code, effectively placing the queued code immediately after the currently executing synchronous
  JavaScript has run to completion.</p>

  <div class=example>
   <p>The most common reason for using <code id=microtask-queuing:dom-queuemicrotask-3><a href=#dom-queuemicrotask>queueMicrotask()</a></code> is
   to create consistent ordering, even in the cases where information is available synchronously,
   without introducing undue delay.</p>

   <p>For example, consider a custom element firing a <code>load</code> event, that also
   maintains an internal cache of previously-loaded data. A naïve implementation might look
   like:</p>

   <pre><code class='js'>MyElement<c- p>.</c->prototype<c- p>.</c->loadData <c- o>=</c-> <c- a>function</c-> <c- p>(</c->url<c- p>)</c-> <c- p>{</c->
  <c- k>if</c-> <c- p>(</c-><c- k>this</c-><c- p>.</c->_cache<c- p>[</c->url<c- p>])</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->_setData<c- p>(</c-><c- k>this</c-><c- p>.</c->_cache<c- p>[</c->url<c- p>]);</c->
    <c- k>this</c-><c- p>.</c->dispatchEvent<c- p>(</c-><c- k>new</c-> Event<c- p>(</c-><c- u>&quot;load&quot;</c-><c- p>));</c->
  <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
    fetch<c- p>(</c->url<c- p>).</c->then<c- p>(</c->res <c- p>=&gt;</c-> res<c- p>.</c->arrayBuffer<c- p>()).</c->then<c- p>(</c->data <c- p>=&gt;</c-> <c- p>{</c->
      <c- k>this</c-><c- p>.</c->_cache<c- p>[</c->url<c- p>]</c-> <c- o>=</c-> data<c- p>;</c->
      <c- k>this</c-><c- p>.</c->_setData<c- p>(</c->data<c- p>);</c->
      <c- k>this</c-><c- p>.</c->dispatchEvent<c- p>(</c-><c- k>new</c-> Event<c- p>(</c-><c- u>&quot;load&quot;</c-><c- p>));</c->
    <c- p>});</c->
  <c- p>}</c->
<c- p>};</c-></code></pre>

   <p>This naïve implementation is problematic, however, in that it causes its users to
   experience inconsistent behavior. For example, code such as</p>

   <pre><code class='js'>element<c- p>.</c->addEventListener<c- p>(</c-><c- u>&quot;load&quot;</c-><c- p>,</c-> <c- p>()</c-> <c- p>=&gt;</c-> console<c- p>.</c->log<c- p>(</c-><c- u>&quot;loaded&quot;</c-><c- p>));</c->
console<c- p>.</c->log<c- p>(</c-><c- u>&quot;1&quot;</c-><c- p>);</c->
element<c- p>.</c->loadData<c- p>();</c->
console<c- p>.</c->log<c- p>(</c-><c- u>&quot;2&quot;</c-><c- p>);</c-></code></pre>

   <p>will sometimes log "1, 2, loaded" (if the data needs to be fetched), and sometimes log "1,
   loaded, 2" (if the data is already cached). Similarly, after the call to <code>loadData()</code>, it will be inconsistent whether or not the data is set on the
   element.</p>

   <p>To get a consistent ordering, <code id=microtask-queuing:dom-queuemicrotask-4><a href=#dom-queuemicrotask>queueMicrotask()</a></code> can be
   used:</p>

   <pre><code class='js'>MyElement<c- p>.</c->prototype<c- p>.</c->loadData <c- o>=</c-> <c- a>function</c-> <c- p>(</c->url<c- p>)</c-> <c- p>{</c->
  <c- k>if</c-> <c- p>(</c-><c- k>this</c-><c- p>.</c->_cache<c- p>[</c->url<c- p>])</c-> <c- p>{</c-><strong>
    queueMicrotask<c- p>(()</c-> <c- p>=&gt;</c-> <c- p>{</c->
      <c- k>this</c-><c- p>.</c->_setData<c- p>(</c-><c- k>this</c-><c- p>.</c->_cache<c- p>[</c->url<c- p>]);</c->
      <c- k>this</c-><c- p>.</c->dispatchEvent<c- p>(</c-><c- k>new</c-> Event<c- p>(</c-><c- u>&quot;load&quot;</c-><c- p>));</c->
    <c- p>});</c-></strong>
  <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
    fetch<c- p>(</c->url<c- p>).</c->then<c- p>(</c->res <c- p>=&gt;</c-> res<c- p>.</c->arrayBuffer<c- p>()).</c->then<c- p>(</c->data <c- p>=&gt;</c-> <c- p>{</c->
      <c- k>this</c-><c- p>.</c->_cache<c- p>[</c->url<c- p>]</c-> <c- o>=</c-> data<c- p>;</c->
      <c- k>this</c-><c- p>.</c->_setData<c- p>(</c->data<c- p>);</c->
      <c- k>this</c-><c- p>.</c->dispatchEvent<c- p>(</c-><c- k>new</c-> Event<c- p>(</c-><c- u>&quot;load&quot;</c-><c- p>));</c->
    <c- p>});</c->
  <c- p>}</c->
<c- p>};</c-></code></pre>

   <p>By essentially rearranging the queued code to be after the <a id=microtask-queuing:javascript-execution-context-stack-2 href=https://tc39.es/ecma262/#execution-context-stack data-x-internal=javascript-execution-context-stack>JavaScript execution context
   stack</a> empties, this ensures a consistent ordering and update of the element's state.</p>
  </div>

  <div class=example>
   <p>Another interesting use of <code id=microtask-queuing:dom-queuemicrotask-5><a href=#dom-queuemicrotask>queueMicrotask()</a></code> is to
   allow uncoordinated "batching" of work by multiple callers. For example, consider a library
   function that wants to send data somewhere as soon as possible, but doesn't want to make multiple
   network requests if doing so is easily avoidable. One way to balance this would be like so:</p>

   <pre><code class='js'><c- a>const</c-> queuedToSend <c- o>=</c-> <c- p>[];</c->

<c- a>function</c-> sendData<c- p>(</c->data<c- p>)</c-> <c- p>{</c->
  queuedToSend<c- p>.</c->push<c- p>(</c->data<c- p>);</c->

  <c- k>if</c-> <c- p>(</c->queuedToSend<c- p>.</c->length <c- o>===</c-> <c- mf>1</c-><c- p>)</c-> <c- p>{</c->
    queueMicrotask<c- p>(()</c-> <c- p>=&gt;</c-> <c- p>{</c->
      <c- a>const</c-> stringToSend <c- o>=</c-> JSON<c- p>.</c->stringify<c- p>(</c->queuedToSend<c- p>);</c->
      queuedToSend<c- p>.</c->length <c- o>=</c-> <c- mf>0</c-><c- p>;</c->

      fetch<c- p>(</c-><c- u>&quot;/endpoint&quot;</c-><c- p>,</c-> stringToSend<c- p>);</c->
    <c- p>});</c->
  <c- p>}</c->
<c- p>}</c-></code></pre>

   <p>With this architecture, multiple subsequent calls to <code>sendData()</code> within
   the currently executing synchronous JavaScript will be batched together into one
   <code id=microtask-queuing:fetch()><a data-x-internal=fetch() href=https://fetch.spec.whatwg.org/#dom-global-fetch>fetch()</a></code> call, but with no intervening event loop tasks preempting the fetch (as
   would have happened with similar code that instead used <code id=microtask-queuing:dom-settimeout-2><a href=#dom-settimeout>setTimeout()</a></code>).</p>
  </div>


  <h3 id=user-prompts><span class=secno>8.8</span> User prompts<a href=#user-prompts class=self-link></a></h3>

  

  <h4 id=simple-dialogs><span class=secno>8.8.1</span> Simple dialogs<a href=#simple-dialogs class=self-link></a></h4>

  <dl class=domintro><dt><code><var>window</var>.<a href=#dom-alert id=dom-alert-dev>alert</a>(<var>message</var>)</code><div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/Window/alert title="window.alert() instructs the browser to display a dialog with an optional message, and to wait until the user dismisses the dialog.">Window/alert</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>1+</span></span><span class="safari yes"><span>Safari</span><span>1+</span></span><span class="chrome yes"><span>Chrome</span><span>1+</span></span><hr><span class="opera yes"><span>Opera</span><span>3+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>4+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>10.1+</span></span></div></div></div><dd><p>Displays a modal alert with the given message, and waits for the user to dismiss
   it.<dt><code><var>result</var> = <var>window</var>.<a href=#dom-confirm id=dom-confirm-dev>confirm</a>(<var>message</var>)</code><div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm title="window.confirm() instructs the browser to display a dialog with an optional message, and to wait until the user either confirms or cancels the dialog.">Window/confirm</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>1+</span></span><span class="safari yes"><span>Safari</span><span>1+</span></span><span class="chrome yes"><span>Chrome</span><span>1+</span></span><hr><span class="opera yes"><span>Opera</span><span>3+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>4+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android yes"><span>WebView Android</span><span>1+</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>10.1+</span></span></div></div></div><dd>
    <p>Displays a modal OK/Cancel prompt with the given message, waits for the user to dismiss it,
    and returns true if the user clicks OK and false if the user clicks Cancel.</p>
   <dt><code><var>result</var> = <var>window</var>.<a href=#dom-prompt id=dom-prompt-dev>prompt</a>(<var>message</var> [, <var>default</var>])</code><div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt title="window.prompt() instructs the browser to display a dialog with an optional message prompting the user to input some text, and to wait until the user either submits the text or cancels the dialog.">Window/prompt</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>1+</span></span><span class="safari yes"><span>Safari</span><span>1+</span></span><span class="chrome yes"><span>Chrome</span><span>1+</span></span><hr><span class="opera yes"><span>Opera</span><span>3+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>4+</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>10.1+</span></span></div></div></div><dd>
    <p>Displays a modal text control prompt with the given message, waits for the user to dismiss
    it, and returns the value that the user entered. If the user cancels the prompt, then returns
    null instead. If the second argument is present, then the given value is used as a default.</p>
   </dl>

  <p class=note>Logic that depends on <a href=webappapis.html#concept-task id=simple-dialogs:concept-task>tasks</a> or <a href=webappapis.html#microtask id=simple-dialogs:microtask>microtasks</a>, such as <a href=media.html#media-element id=simple-dialogs:media-element>media elements</a>
  loading their <a id=simple-dialogs:media-data href=media.html#media-data>media data</a>, are stalled when these methods are invoked.</p>

  

  <p>The <dfn data-dfn-for=Window id=dom-alert-noargs data-dfn-type=method><code>alert()</code></dfn> and <dfn data-dfn-for=Window id=dom-alert data-dfn-type=method><code>alert(<var>message</var>)</code></dfn> method steps
  are:</p>

  <ol><li><p>If we <a href=#cannot-show-simple-dialogs id=simple-dialogs:cannot-show-simple-dialogs>cannot show simple dialogs</a> for <a id=simple-dialogs:this href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>, then return.<li><p>If the method was invoked with no arguments, then let <var>message</var> be the
   empty string; otherwise, let <var>message</var> be the method's first
   argument.<li><p>Set <var>message</var> to the result of <a href=https://infra.spec.whatwg.org/#normalize-newlines id=simple-dialogs:normalize-newlines data-x-internal=normalize-newlines>normalizing
   newlines</a> given <var>message</var>.<li><p>Set <var>message</var> to the result of <a href=#optionally-truncate-a-simple-dialog-string id=simple-dialogs:optionally-truncate-a-simple-dialog-string>optionally truncating</a> <var>message</var>.<li><p>Let <var>userPromptHandler</var> be <a id=simple-dialogs:webdriver-bidi-user-prompt-opened href=https://w3c.github.io/webdriver-bidi/#webdriver-bidi-user-prompt-opened data-x-internal=webdriver-bidi-user-prompt-opened>WebDriver BiDi user prompt opened</a> with
   <a id=simple-dialogs:this-2 href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>, "<code>alert</code>", and <var>message</var>.<li>
    <p>If <var>userPromptHandler</var> is "<code>none</code>", then:</p>

    <ol><li><p>Show <var>message</var> to the user, treating U+000A LF as a line break.<li><p>Optionally, <a id=simple-dialogs:pause href=webappapis.html#pause>pause</a> while waiting for the user to acknowledge the
     message.</ol>
   <li><p>Invoke <a id=simple-dialogs:webdriver-bidi-user-prompt-closed href=https://w3c.github.io/webdriver-bidi/#webdriver-bidi-user-prompt-closed data-x-internal=webdriver-bidi-user-prompt-closed>WebDriver BiDi user prompt closed</a> with <a id=simple-dialogs:this-3 href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>,
   "<code>alert</code>", and true.</ol>

  <p class=note>This method is defined using two overloads, instead of using an
  optional argument, for historical reasons. The practical impact of this is
  that <code class=js>alert(undefined)</code> is treated as <code class=js>alert("undefined")</code>, but <code class=js>alert()</code> is treated as
  <code class=js>alert("")</code>.</p>

  <p>The <dfn data-dfn-for=Window id=dom-confirm data-dfn-type=method><code>confirm(<var>message</var>)</code></dfn> method steps are:</p>

  <ol><li><p>If we <a href=#cannot-show-simple-dialogs id=simple-dialogs:cannot-show-simple-dialogs-2>cannot show simple dialogs</a> for <a id=simple-dialogs:this-4 href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>, then return
   false.<li><p>Set <var>message</var> to the result of <a href=https://infra.spec.whatwg.org/#normalize-newlines id=simple-dialogs:normalize-newlines-2 data-x-internal=normalize-newlines>normalizing
   newlines</a> given <var>message</var>.<li><p>Set <var>message</var> to the result of <a href=#optionally-truncate-a-simple-dialog-string id=simple-dialogs:optionally-truncate-a-simple-dialog-string-2>optionally truncating</a> <var>message</var>.<li><p>Show <var>message</var> to the user, treating U+000A LF as a line break, and ask the user
   to respond with a positive or negative response.<li><p>Let <var>userPromptHandler</var> be <a id=simple-dialogs:webdriver-bidi-user-prompt-opened-2 href=https://w3c.github.io/webdriver-bidi/#webdriver-bidi-user-prompt-opened data-x-internal=webdriver-bidi-user-prompt-opened>WebDriver BiDi user prompt opened</a> with
   <a id=simple-dialogs:this-5 href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>, "<code>confirm</code>", and <var>message</var>.<li><p>Let <var>accepted</var> be false.<li>
    <p>If <var>userPromptHandler</var> is "<code>none</code>", then:</p>

    <ol><li><p><a id=simple-dialogs:pause-2 href=webappapis.html#pause>Pause</a> until the user responds either positively or negatively.<li><p>If the user responded positively, then set <var>accepted</var> to true.</ol>
   <li><p>If <var>userPromptHandler</var> is "<code>accept</code>", then set
   <var>accepted</var> to true.<li><p>Invoke <a id=simple-dialogs:webdriver-bidi-user-prompt-closed-2 href=https://w3c.github.io/webdriver-bidi/#webdriver-bidi-user-prompt-closed data-x-internal=webdriver-bidi-user-prompt-closed>WebDriver BiDi user prompt closed</a> with <a id=simple-dialogs:this-6 href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>,
   "<code>confirm</code>", and <var>accepted</var>.<li><p>Return <var>accepted</var>.</ol>

  <p>The <dfn data-dfn-for=Window id=dom-prompt data-dfn-type=method><code>prompt(<var>message</var>,
  <var>default</var>)</code></dfn> method steps are:</p>

  <ol><li><p>If we <a href=#cannot-show-simple-dialogs id=simple-dialogs:cannot-show-simple-dialogs-3>cannot show simple dialogs</a> for <a id=simple-dialogs:this-7 href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>, then return
   null.<li><p>Set <var>message</var> to the result of <a href=https://infra.spec.whatwg.org/#normalize-newlines id=simple-dialogs:normalize-newlines-3 data-x-internal=normalize-newlines>normalizing
   newlines</a> given <var>message</var>.<li><p>Set <var>message</var> to the result of <a href=#optionally-truncate-a-simple-dialog-string id=simple-dialogs:optionally-truncate-a-simple-dialog-string-3>optionally truncating</a> <var>message</var>.<li><p>Set <var>default</var> to the result of <a href=#optionally-truncate-a-simple-dialog-string id=simple-dialogs:optionally-truncate-a-simple-dialog-string-4>optionally truncating</a> <var>default</var>.<li><p>Show <var>message</var> to the user, treating U+000A LF as a line break, and ask the user
   to either respond with a string value or abort. The response must be defaulted to the value given
   by <var>default</var>.<li><p>Let <var>userPromptHandler</var> be <a id=simple-dialogs:webdriver-bidi-user-prompt-opened-3 href=https://w3c.github.io/webdriver-bidi/#webdriver-bidi-user-prompt-opened data-x-internal=webdriver-bidi-user-prompt-opened>WebDriver BiDi user prompt opened</a> with
   <a id=simple-dialogs:this-8 href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>, "<code>prompt</code>", and <var>message</var>.<li><p>Let <var>result</var> be null.<li>
    <p>If <var>userPromptHandler</var> is "<code>none</code>", then:</p>

    <ol><li><p><a id=simple-dialogs:pause-3 href=webappapis.html#pause>Pause</a> while waiting for the user's response.<li><p>If the user did not abort, then set <var>result</var> to the string that the user
     responded with.</ol>
   <li><p>Otherwise, if <var>userPromptHandler</var> is "<code>accept</code>", then set
   <var>result</var> to the empty string.<li><p>Invoke <a id=simple-dialogs:webdriver-bidi-user-prompt-closed-3 href=https://w3c.github.io/webdriver-bidi/#webdriver-bidi-user-prompt-closed data-x-internal=webdriver-bidi-user-prompt-closed>WebDriver BiDi user prompt closed</a> with <a id=simple-dialogs:this-9 href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>,
   "<code>prompt</code>", false if <var>result</var> is null or true otherwise,
   and <var>result</var>.<li><p>Return <var>result</var>.</ol>

  <p>To <dfn id=optionally-truncate-a-simple-dialog-string>optionally truncate a simple dialog string</dfn> <var>s</var>, return either
  <var>s</var> itself or some string derived from <var>s</var> that is shorter. User agents should
  not provide UI for displaying the elided portion of <var>s</var>, as this makes it too easy for
  abusers to create dialogs of the form "Important security alert! Click 'Show More' for full
  details!".</p>

  <p class=note>For example, a user agent might want to only display the first 100 characters of a
  message. Or, a user agent might replace the middle of the string with "…". These types of
  modifications can be useful in limiting the abuse potential of unnaturally large,
  trustworthy-looking system dialogs.</p>

  <p>We <dfn id=cannot-show-simple-dialogs>cannot show simple dialogs</dfn> for a <code id=simple-dialogs:window><a href=nav-history-apis.html#window>Window</a></code> <var>window</var> when the
  following algorithm returns true:</p>

  <ol><li><p>If the <a id=simple-dialogs:active-sandboxing-flag-set href=browsers.html#active-sandboxing-flag-set>active sandboxing flag set</a> of <var>window</var>'s <a href=nav-history-apis.html#concept-document-window id=simple-dialogs:concept-document-window>associated <code>Document</code></a> has the <a id=simple-dialogs:sandboxed-modals-flag href=browsers.html#sandboxed-modals-flag>sandboxed
   modals flag</a> set, then return true.<li><p>If <var>window</var>'s <a id=simple-dialogs:relevant-settings-object href=webappapis.html#relevant-settings-object>relevant settings object</a>'s <a href=webappapis.html#concept-settings-object-origin id=simple-dialogs:concept-settings-object-origin>origin</a> and <var>window</var>'s <a id=simple-dialogs:relevant-settings-object-2 href=webappapis.html#relevant-settings-object>relevant
   settings object</a>'s <a id=simple-dialogs:concept-environment-top-level-origin href=webappapis.html#concept-environment-top-level-origin>top-level origin</a> are not <a id=simple-dialogs:same-origin-domain href=browsers.html#same-origin-domain>same origin-domain</a>,
   then return true.<li>If <var>window</var>'s <a id=simple-dialogs:relevant-agent href=webappapis.html#relevant-agent>relevant agent</a>'s <a href=webappapis.html#concept-agent-event-loop id=simple-dialogs:concept-agent-event-loop>event loop</a>'s <a id=simple-dialogs:termination-nesting-level href=document-lifecycle.html#termination-nesting-level>termination nesting level</a> is
   nonzero, then optionally return true.<li><p>Optionally, return true. (For example, the user agent might give the
   user the option to ignore all modal dialogs, and would thus abort at this step whenever the method was
   invoked.)<li><p>Return false.</ol>

  


  <h4 id=printing><span class=secno>8.8.2</span> Printing<a href=#printing class=self-link></a></h4><div class="mdn-anno wrapped"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/Window/print title="Opens the print dialog to print the current document.">Window/print</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>1+</span></span><span class="safari yes"><span>Safari</span><span>1.1+</span></span><span class="chrome yes"><span>Chrome</span><span>1+</span></span><hr><span class="opera yes"><span>Opera</span><span>6+</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge yes"><span>Edge (Legacy)</span><span>12+</span></span><span class="ie yes"><span>Internet Explorer</span><span>5+</span></span><hr><span class="firefox_android yes"><span>Firefox Android</span><span>114+</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android yes"><span>Opera Android</span><span>10.1+</span></span></div></div></div>

  <dl class=domintro><dt><code><var>window</var>.<a href=#dom-print id=dom-print-dev>print</a>()</code><dd><p>Prompts the user to print the page.</dl>

  

  <p>The <dfn data-dfn-for=Window id=dom-print data-dfn-type=method><code>print()</code></dfn> method steps
  are:</p>

  <ol><li><p>Let <var>document</var> be <a id=printing:this href=https://webidl.spec.whatwg.org/#this data-x-internal=this>this</a>'s <a href=nav-history-apis.html#concept-document-window id=printing:concept-document-window>associated <code>Document</code></a>.<li><p>If <var>document</var> is not <a id=printing:fully-active href=document-sequences.html#fully-active>fully active</a>, then return.<li><p>If <var>document</var>'s <a id=printing:unload-counter href=document-lifecycle.html#unload-counter>unload counter</a> is greater than 0, then
   return.<li><p>If <var>document</var> is <a id=printing:ready-for-post-load-tasks href=parsing.html#ready-for-post-load-tasks>ready for post-load tasks</a>, then run the
   <a href=#printing-steps id=printing:printing-steps>printing steps</a> for <var>document</var>.<li><p>Otherwise, set <var>document</var>'s <dfn id=print-when-loaded>print when loaded</dfn> flag.</ol>

  <p>User agents should also run the <a href=#printing-steps id=printing:printing-steps-2>printing steps</a> whenever the user asks for the
  opportunity to <a id=printing:obtain-a-physical-form href=rendering.html#obtain-a-physical-form>obtain a physical form</a> (e.g. printed copy), or the representation of a
  physical form (e.g. PDF copy), of a document.</p>

  <p>The <dfn id=printing-steps>printing steps</dfn> for a <code id=printing:document><a href=dom.html#document>Document</a></code> <var>document</var> are:</p>

  <ol><li>
    <p>The user agent may display a message to the user or return (or both).</p>

    <p class=example>For instance, a kiosk browser could silently ignore any invocations of the
    <code id=printing:dom-print><a href=#dom-print>print()</a></code> method.</p>

    <p class=example>For instance, a browser on a mobile device could detect that there are no
    printers in the vicinity and display a message saying so before continuing to offer a "save to
    PDF" option.</p>
   <li>
    <p>If the <a id=printing:active-sandboxing-flag-set href=browsers.html#active-sandboxing-flag-set>active sandboxing flag set</a> of <var>document</var> has the <a id=printing:sandboxed-modals-flag href=browsers.html#sandboxed-modals-flag>sandboxed
    modals flag</a> set, then return.</p>

    <p class=note>If the printing dialog is blocked by a <code id=printing:document-2><a href=dom.html#document>Document</a></code>'s sandbox,
    then neither the <code id=printing:event-beforeprint><a href=indices.html#event-beforeprint>beforeprint</a></code> nor <code id=printing:event-afterprint><a href=indices.html#event-afterprint>afterprint</a></code> events will be fired.</p>
   <li>
    <p>The user agent must <a href=https://dom.spec.whatwg.org/#concept-event-fire id=printing:concept-event-fire data-x-internal=concept-event-fire>fire an event</a> named <code id=printing:event-beforeprint-2><a href=indices.html#event-beforeprint>beforeprint</a></code> at the <a id=printing:concept-relevant-global href=webappapis.html#concept-relevant-global>relevant global object</a> of
    <var>document</var>, as well as any <a href=document-sequences.html#child-navigable id=printing:child-navigable>child navigable</a> in
    it.</p>

    <p class=XXX>Firing in children only doesn't seem right here, and some tasks likely need to
    be queued. See <a href=https://github.com/whatwg/html/issues/5096>issue #5096</a>.</p>

    <p class=example>The <code id=printing:event-beforeprint-3><a href=indices.html#event-beforeprint>beforeprint</a></code> event can be used to
    annotate the printed copy, for instance adding the time at which the document was printed.</p>
   <li><p>The user agent should offer the user the opportunity to <a id=printing:obtain-a-physical-form-2 href=rendering.html#obtain-a-physical-form>obtain a physical
   form</a> (or the representation of a physical form) of <var>document</var>. The user agent may
   wait for the user to either accept or decline before returning; if so, the user agent must
   <a id=printing:pause href=webappapis.html#pause>pause</a> while the method is waiting. Even if the user agent doesn't wait at this
   point, the user agent must use the state of the relevant documents as they are at this point in
   the algorithm if and when it eventually creates the alternate form.<li>
    <p>The user agent must <a href=https://dom.spec.whatwg.org/#concept-event-fire id=printing:concept-event-fire-2 data-x-internal=concept-event-fire>fire an event</a> named <code id=printing:event-afterprint-2><a href=indices.html#event-afterprint>afterprint</a></code> at the <a id=printing:concept-relevant-global-2 href=webappapis.html#concept-relevant-global>relevant global object</a> of
    <var>document</var>, as well as any <a href=document-sequences.html#child-navigable id=printing:child-navigable-2>child navigables</a> in
    it.</p>

    <p class=XXX>Firing in children only doesn't seem right here, and some tasks likely need to
    be queued. See <a href=https://github.com/whatwg/html/issues/5096>issue #5096</a>.</p>

    <p class=example>The <code id=printing:event-afterprint-3><a href=indices.html#event-afterprint>afterprint</a></code> event can be used to
    revert annotations added in the earlier event, as well as showing post-printing UI. For
    instance, if a page is walking the user through the steps of applying for a home loan, the
    script could automatically advance to the next step after having printed a form or other.</p>
   </ol>

  


  <nav><a href=dynamic-markup-insertion.html>← 8.4 Dynamic markup insertion</a> — <a href=index.html>Table of Contents</a> — <a href=system-state.html>8.9 System state and capabilities →</a></nav>
